<template>
  <!-- 情况一：添加/修改 -->
  <el-table
    v-if="!isDetail && !isActivityComponent"
    :data="isBatch ? skuList : formData!.skus!"
    border
    class="tabNumWidth"
    max-height="500"
    size="small"
  >
    <el-table-column align="center" label="图片" width="65">
      <template #default="{ row }">
        <UploadImg v-model="row.picUrl" :showDelete="!isDetail" height="50px" width="50px" />
      </template>
    </el-table-column>
    <template v-if="formData!.specType && !isBatch">
      <!--  根据商品属性动态添加 -->
      <el-table-column
        v-for="(item, index) in tableHeaders"
        :key="index"
        :label="item.label"
        align="center"
        min-width="120"
      >
        <template #default="{ row }">
          <span style="font-weight: bold; color: #40aaff" v-if="row.properties?.length > 0">
            {{ row.properties[index]?.valueName }}
          </span>
        </template>
      </el-table-column>
    </template>
    <el-table-column align="center" label="商品属性 " min-width="168">
      <template #default="{ row }">
        <el-select v-model="row.skuType" placeholder="请选择商品属性" clearable class="w-100%!">
          <el-option
            v-for="dict in getIntDictOptions(DICT_TYPE[`PRODUCT_SPU_TYPE${formData?.spuType}`])"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </template>
    </el-table-column>
    <!-- <el-table-column align="center" label="关联素材" min-width="168">
      <template #header>
        <div class="flex flex-items-center flex-justify-center">
          关联素材
          <el-popover placement="top" trigger="hover" content="关联素材">
            <template #reference>
              <Icon :icon="'ep:question-filled'" />
            </template>
          </el-popover>
        </div>
      </template>
      <template #default="{ row }">
        <el-button @click="addFile('file', row)" v-if="!row.tvAssociatedMaterial"
          >关联素材</el-button
        >
        <el-popover placement="top" trigger="hover" :content="row.tvAssociatedMaterial.name" v-else>
          <template #reference>
            <el-tag type="success" closable @close="handleCloseFile(row)">
              <div class="w-128px">
                <el-text truncated type="success">{{ row.tvAssociatedMaterial.name }}</el-text>
              </div>
            </el-tag>
          </template>
        </el-popover>
      </template>
    </el-table-column> -->
    <el-table-column align="center" label="售卖方式" min-width="168">
      <template #header>
        <div class="flex flex-items-center flex-justify-center">
          售卖方式
          <el-popover placement="top" trigger="hover" content="售卖方式">
            <template #reference>
              <Icon :icon="'ep:question-filled'" />
            </template>
          </el-popover>
        </div>
      </template>
      <template #default="{ row }">
        <el-select v-model="row.tvSaleMethodType" placeholder="请选择售卖方式" class="w-100%!">
          <el-option
            v-for="dict in getIntDictOptions(DICT_TYPE.TV_SALE_METHOD_TYPE)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </template>
    </el-table-column>
    <el-table-column align="center" label="零售价(元)" min-width="168">
      <template #header>
        <div class="flex flex-items-center flex-justify-center">
          零售价
          <el-popover placement="top" trigger="hover" content="商品销售价格">
            <template #reference>
              <Icon :icon="'ep:question-filled'" />
            </template>
          </el-popover>
        </div>
      </template>
      <template #default="{ row }">
        <el-input-number
          v-if="row.tvSaleMethodType == 1"
          v-model="row.price"
          :min="0"
          :precision="2"
          :step="0.1"
          class="w-100%!"
          :controls="false"
        >
          <template #suffix>
            <span>元</span>
          </template>
        </el-input-number>
        <div v-else> - </div>
      </template>
    </el-table-column>
    <el-table-column
      align="center"
      label="划线价(元)"
      min-width="168"
      v-if="formData?.salesChannel?.includes(2)"
    >
      <template #header>
        <div class="flex flex-items-center flex-justify-center">
          划线价
          <el-popover placement="top" trigger="hover" content="线上展示使用，建议填写商品指导价">
            <template #reference>
              <Icon :icon="'ep:question-filled'" />
            </template>
          </el-popover>
        </div>
      </template>
      <template #default="{ row }">
        <el-input-number
          v-if="row.tvSaleMethodType == 1"
          v-model="row.marketPrice"
          :min="0"
          :precision="2"
          :step="0.1"
          class="w-100%!"
          :controls="false"
        >
          <template #suffix>
            <span>元</span>
          </template>
        </el-input-number>
        <div v-else> - </div>
      </template>
    </el-table-column>
    <el-table-column
      align="center"
      label="最低价(元)"
      min-width="168"
      v-if="formData?.salesChannel?.includes(1)"
    >
      <template #header>
        <div class="flex flex-items-center flex-justify-center">
          最低价
          <el-popover
            placement="top"
            trigger="hover"
            content="商品控价价格，低于该价格商品禁止销售"
          >
            <template #reference>
              <Icon :icon="'ep:question-filled'" />
            </template>
          </el-popover>
        </div>
      </template>
      <template #default="{ row }">
        <el-input-number
          v-if="row.tvSaleMethodType == 1"
          v-model="row.lowPrice"
          :min="0"
          :precision="2"
          :step="0.1"
          class="w-100%!"
          :controls="false"
        >
          <template #suffix>
            <span>元</span>
          </template>
        </el-input-number>
        <div v-else> - </div>
      </template>
    </el-table-column>
    <el-table-column align="center" label="成本价(元)" min-width="168">
      <template #header>
        <div class="flex flex-items-center flex-justify-center">
          成本价
          <el-popover
            placement="top"
            trigger="hover"
            content="商品成本价格，用来核算商品利润，不填写则无法核算利润"
          >
            <template #reference>
              <Icon :icon="'ep:question-filled'" />
            </template>
          </el-popover>
        </div>
      </template>
      <template #default="{ row }">
        <el-input-number
          v-if="row.tvSaleMethodType == 1"
          v-model="row.costPrice"
          :min="0"
          :precision="2"
          :step="0.1"
          class="w-100%!"
          :controls="false"
        >
          <template #suffix>
            <span>元</span>
          </template>
        </el-input-number>
        <div v-else> - </div>
      </template>
    </el-table-column>
    <!-- <el-table-column align="center" label="密码设置" min-width="168">
      <template #header>
        <div class="flex flex-items-center flex-justify-center">
          密码设置
          <el-popover placement="top" trigger="hover" content="密码设置">
            <template #reference>
              <Icon :icon="'ep:question-filled'" />
            </template>
          </el-popover>
        </div>
      </template>
      <template #default="{ row }">
        <el-input
          v-model="row.tvPassWord"
          autocomplete="new-password"
          type="password"
          class="w-100%!"
          v-if="row.tvSaleMethodType == 2"
        />
        <div v-else> - </div>
      </template>
    </el-table-column>
    <el-table-column align="center" label="有效期" min-width="188">
      <template #header>
        <div class="flex flex-items-center flex-justify-center">
          有效期
          <el-popover placement="top" trigger="hover" content="有效期">
            <template #reference>
              <Icon :icon="'ep:question-filled'" />
            </template>
          </el-popover>
        </div>
      </template>
      <template #default="{ row }">
        <el-input v-model="row.expiryDate" :disabled="row.expiryDateUnit == 3">
          <template #append>
            <el-select v-model="row.expiryDateUnit" class="w-80px!">
              <el-option
                v-for="dict in getIntDictOptions(DICT_TYPE.SPU_CARD_DATE_UNIT)"
                :key="dict.value"
                :label="dict.label"
                :value="dict.value"
              />
            </el-select>
          </template>
        </el-input>
      </template>
    </el-table-column>
    <el-table-column align="center" label="文字描述" min-width="188">
      <template #default="{ row }">
        <el-input v-model="row.tvRemark" class="w-100%!" />
      </template>
    </el-table-column> -->

    <slot name="EditExtension"></slot>

    <el-table-column v-if="formData?.specType" align="center" fixed="right" label="操作" width="80">
      <template #default="{ row }">
        <el-button v-if="isBatch" link size="small" type="primary" @click="batchAdd">
          批量添加
        </el-button>
        <el-button v-else link size="small" type="primary" @click="deleteSku(row)">删除</el-button>
      </template>
    </el-table-column>
  </el-table>

  <!-- 情况二：详情 -->
  <el-table
    v-if="isDetail"
    ref="activitySkuListRef"
    :data="formData!.skus!"
    border
    max-height="500"
    size="small"
    style="width: 99%"
    @selection-change="handleSelectionChange"
  >
    <el-table-column v-if="isComponent" type="selection" width="45" />
    <el-table-column align="center" label="图片" min-width="80">
      <template #default="{ row }">
        <el-image
          v-if="row.picUrl"
          :src="row.picUrl"
          class="h-50px w-50px"
          @click="imagePreview(row.picUrl)"
        />
      </template>
    </el-table-column>
    <template v-if="formData!.specType && !isBatch">
      <!--  根据商品属性动态添加 -->
      <el-table-column
        v-for="(item, index) in tableHeaders"
        :key="index"
        :label="item.label"
        align="center"
        min-width="80"
      >
        <template #default="{ row }">
          <span style="font-weight: bold; color: #40aaff">
            {{ row.properties[index]?.valueName }}
          </span>
        </template>
      </el-table-column>
    </template>

    <el-table-column align="center" label="商品属性" min-width="168">
      <template #default="{ row }">
        <dict-tag :type="DICT_TYPE[`PRODUCT_SPU_TYPE${formData?.spuType}`]" :value="row.skuType" />
      </template>
    </el-table-column>
    <el-table-column align="center" label="关联素材" min-width="168">
      <template #default="{ row }">
        <el-popover placement="top" trigger="hover" :content="row.tvAssociatedMaterial.name">
          <template #reference>
            <el-tag type="success" closable @close="handleCloseFile(row)">
              <div class="w-128px">
                <el-text truncated type="success">{{ row.tvAssociatedMaterial.name }}</el-text>
              </div>
            </el-tag>
          </template>
        </el-popover>
      </template>
    </el-table-column>
    <el-table-column align="center" label="零售价(元)" min-width="80">
      <template #default="{ row }">
        {{ row.price }}
      </template>
    </el-table-column>
    <el-table-column align="center" label="成本价(元)" min-width="80">
      <template #default="{ row }"> {{ row.costPrice }} </template>
    </el-table-column>
    <el-table-column align="center" label="售卖方式" min-width="168">
      <template #default="{ row }">
        <dict-tag :type="DICT_TYPE.TV_SALE_METHOD_TYPE" :value="row.tvSaleMethodType" />
      </template>
    </el-table-column>
    <el-table-column align="center" label="密码设置" min-width="80">
      <template #default="{ row }">
        {{ row.tvPassWord }}
      </template>
    </el-table-column>
    <el-table-column align="center" label="有效期" min-width="80">
      <template #default="{ row }"> {{ row.expiryDate }} {{ row.expiryDateUnit }} </template>
    </el-table-column>
    <el-table-column align="center" label="文字描述" min-width="188">
      <template #default="{ row }">
        {{ row.tvRemark }}
      </template>
    </el-table-column>

    <slot name="DetailExtension"></slot>
  </el-table>

  <!-- 素材管理弹窗 -->
  <!-- <FileSelect ref="FileSelectRef" @success="setFile" /> -->
  <upload-attachment type="2" ref="FileSelectRef" @confirm="setFile" />
</template>
<script lang="ts" setup>
import { PropType, Ref } from 'vue'
import { copyValueToTarget, fenToYuan } from '@/utils'
import { propTypes } from '@/utils/propTypes'
import { UploadImg } from '@/components/UploadFile'
import type { Property, Sku, Spu } from '@/api/mall/product/spu'
import { createImageViewer } from '@/components/ImageViewer'
import UploadAttachment from '@/views/app/components/upload-attachment/index.vue'

import {
  RuleConfig,
  PropertyAndValues,
  fromDataRule
} from '@/views/mall/product/spu/components/index'
import { ElTable } from 'element-plus'
import { isEmpty } from '@/utils/is'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'

defineOptions({ name: 'SkuList' })
const message = useMessage() // 消息弹窗

const props = defineProps({
  propFormData: {
    type: Object as PropType<Spu>,
    default: () => {}
  },
  propertyList: {
    type: Array as PropType<PropertyAndValues[]>,
    default: () => []
  },
  ruleConfig: {
    type: Array as PropType<RuleConfig[]>,
    default: () => []
  },
  isBatch: propTypes.bool.def(false), // 是否作为批量操作组件
  isDetail: propTypes.bool.def(false), // 是否作为 sku 详情组件
  isComponent: propTypes.bool.def(false), // 是否作为 sku 选择组件
  isActivityComponent: propTypes.bool.def(false) // 是否作为 sku 活动配置组件
})
const formData: Ref<Spu | undefined> = ref<Spu>() // 表单数据
const skuList = ref<Sku[]>([
  {
    price: 0, // 商品价格
    marketPrice: 0, // 市场价
    costPrice: 0, // 成本价
    picUrl: '', // 图片地址
    lowPrice: 0, //最低价
    skuType: 62,
    expiryDate: undefined, //有效期
    expiryDateUnit: 0, //有效期单位
    tvAssociatedMaterial: undefined, //视频关联素材,
    tvSaleMethodType: 0, //售卖方式类型 0 免费 1 收费 2 加密
    tvPassWord: '', //视频|商品 售卖方式类型=2 加密后设置的密码
    tvRemark: '' //视频商品每集文字说明
  }
]) // 批量添加时的临时数据

/** 商品图预览 */
const imagePreview = (imgUrl: string) => {
  createImageViewer({
    zIndex: 9999999,
    urlList: [imgUrl]
  })
}

/** 批量添加 */
const batchAdd = () => {
  validateProperty()
  formData.value!.skus!.forEach((item) => {
    copyValueToTarget(item, skuList.value[0])
  })
}
/** 校验商品属性属性值 */
const validateProperty = () => {
  // 校验商品属性属性值是否为空，有一个为空都不给过
  const warningInfo = '存在属性属性值为空，请先检查完善属性值后重试！！！'
  for (const item of props.propertyList) {
    if (!item.values || isEmpty(item.values)) {
      message.warning(warningInfo)
      throw new Error(warningInfo)
    }
  }
}
/** 删除 sku */
const deleteSku = (row) => {
  const index = formData.value!.skus!.findIndex(
    // 直接把列表转成字符串比较
    (sku) => JSON.stringify(sku.properties) === JSON.stringify(row.properties)
  )
  formData.value!.skus!.splice(index, 1)
}
const tableHeaders = ref<{ prop: string; label: string }[]>([]) // 多属性表头
/**
 * 保存时，每个商品规格的表单要校验下。例如说，销售金额最低是 0.01 这种。
 */
const validateSku = () => {
  validateProperty()
  let warningInfo = '请检查商品各行相关属性配置，'
  let validate = true // 默认通过
  for (const sku of formData.value!.skus!) {
    console.log(sku)
    // 作为活动组件的校验
    for (const rule of props?.ruleConfig) {
      const arg = getValue(sku, rule.name)
      if (!rule.rule(arg)) {
        validate = false // 只要有一个不通过则直接不通过
        warningInfo += rule.message
        break
      }
    }
    // 只要有一个不通过则结束后续的校验
    if (!validate) {
      message.warning(warningInfo)
      throw new Error(warningInfo)
    }
  }
}
const getValue = (obj, arg) => {
  const keys = arg.split('.')
  let value = obj
  for (const key of keys) {
    if (value && typeof value === 'object' && key in value) {
      value = value[key]
    } else {
      value = undefined
      break
    }
  }
  return value
}

const emit = defineEmits<{
  (e: 'selectionChange', value: Sku[]): void
}>()
/**
 * 选择时触发
 * @param Sku 传递过来的选中的 sku 是一个数组
 */
const handleSelectionChange = (val: Sku[]) => {
  emit('selectionChange', val)
}

/**
 * 将传进来的值赋值给 skuList
 */
watch(
  () => props.propFormData,
  (data) => {
    if (!data) return
    formData.value = data
  },
  {
    deep: true,
    immediate: true
  }
)

/** 生成表数据 */
const generateTableData = (propertyList: any[]) => {
  // 构建数据结构
  const propertyValues = propertyList.map((item) =>
    item.values.map((v: any) => ({
      propertyId: item.id,
      propertyName: item.name,
      valueId: v.id,
      valueName: v.name
    }))
  )
  const buildSkuList = build(propertyValues)
  // 如果回显的 sku 属性和添加的属性不一致则重置 skus 列表
  if (!validateData(propertyList)) {
    // 如果不一致则重置表数据，默认添加新的属性重新生成 sku 列表
    formData.value!.skus = []
    // 用来重置规则的
    Object.assign(formData.value!, fromDataRule)
  }
  for (const item of buildSkuList) {
    const row = {
      properties: Array.isArray(item) ? item : [item], // 如果只有一个属性的话返回的是一个 property 对象
      price: 0, // 商品价格
      marketPrice: 0, // 市场价
      costPrice: 0, // 成本价
      picUrl: '', // 图片地址
      lowPrice: 0, //最低价
      skuType: 62,
      expiryDate: undefined, //有效期
      expiryDateUnit: 0, //有效期单位
      tvAssociatedMaterial: undefined, //视频关联素材,
      tvSaleMethodType: 0, //售卖方式类型 0 免费 1 收费 2 加密
      tvPassWord: '', //视频|商品 售卖方式类型=2 加密后设置的密码
      tvRemark: '' //视频商品每集文字说明
    }

    // 如果存在属性相同的 sku 则不做处理
    const index = formData.value!.skus!.findIndex(
      (sku) => JSON.stringify(sku.properties) === JSON.stringify(row.properties)
    )
    if (index !== -1) {
      continue
    }
    formData.value!.skus!.push(row)
  }
}

/**
 * 生成 skus 前置校验
 */
const validateData = (propertyList: any[]) => {
  const skuPropertyIds: number[] = []
  formData.value!.skus!.forEach((sku) =>
    sku.properties
      ?.map((property) => property.propertyId)
      ?.forEach((propertyId) => {
        if (skuPropertyIds.indexOf(propertyId!) === -1) {
          skuPropertyIds.push(propertyId!)
        }
      })
  )
  const propertyIds = propertyList.map((item) => item.id)
  return skuPropertyIds.length === propertyIds.length
}

/** 构建所有排列组合 */
const build = (propertyValuesList: Property[][]) => {
  if (propertyValuesList.length === 0) {
    return []
  } else if (propertyValuesList.length === 1) {
    return propertyValuesList[0]
  } else {
    const result: Property[][] = []
    const rest = build(propertyValuesList.slice(1))
    for (let i = 0; i < propertyValuesList[0].length; i++) {
      for (let j = 0; j < rest.length; j++) {
        // 第一次不是数组结构，后面的都是数组结构
        if (Array.isArray(rest[j])) {
          result.push([propertyValuesList[0][i], ...rest[j]])
        } else {
          result.push([propertyValuesList[0][i], rest[j]])
        }
      }
    }
    return result
  }
}

/** 素材管理*/
const FileSelectRef = ref()
const addFileType = ref('') //素材管理选择的类型
const operateRow = ref() //操作的行
// 素材选中
const addFile = (type: string, row: any) => {
  addFileType.value = type
  operateRow.value = row
  FileSelectRef.value.showDialog = true
}
const setFile = (fileList) => {
  if (addFileType.value == 'file') {
    operateRow.value.tvAssociatedMaterial = fileList[0]
  }
}
//素材删除
const handleCloseFile = (row: any) => {
  row.tvAssociatedMaterial = undefined
}
/** 监听属性列表，生成相关参数和表头 */
watch(
  () => props.propertyList,
  (propertyList: PropertyAndValues[]) => {
    // 如果不是多规格则结束
    if (!formData.value!.specType) {
      return
    }
    // 如果当前组件作为批量添加数据使用，则重置表数据
    if (props.isBatch) {
      skuList.value = [
        {
          price: 0, // 商品价格
          marketPrice: 0, // 市场价
          costPrice: 0, // 成本价
          picUrl: '', // 图片地址
          lowPrice: 0, //最低价
          skuType: 62,
          expiryDate: undefined, //有效期
          expiryDateUnit: 0, //有效期单位
          tvAssociatedMaterial: undefined, //视频关联素材,
          tvSaleMethodType: 0, //售卖方式类型 0 免费 1 收费 2 加密
          tvPassWord: '', //视频|商品 售卖方式类型=2 加密后设置的密码
          tvRemark: '' //视频商品每集文字说明
        }
      ]
    }

    // 判断代理对象是否为空
    if (JSON.stringify(propertyList) === '[]') {
      return
    }
    // 重置表头
    tableHeaders.value = []
    // 生成表头
    propertyList.forEach((item, index) => {
      // name加属性项index区分属性值
      tableHeaders.value.push({ prop: `name${index}`, label: item.name })
    })
    // 如果回显的 sku 属性和添加的属性一致则不处理
    if (validateData(propertyList)) {
      return
    }
    // 添加新属性没有属性值也不做处理
    if (propertyList.some((item) => !item.values || isEmpty(item.values))) {
      return
    }
    // 生成 table 数据，即 sku 列表
    generateTableData(propertyList)
  },
  {
    deep: true,
    immediate: true
  }
)
const activitySkuListRef = ref<InstanceType<typeof ElTable>>()

const getSkuTableRef = () => {
  return activitySkuListRef.value
}
// 暴露出生成 sku 方法，给添加属性成功时调用
defineExpose({ generateTableData, validateSku, getSkuTableRef })
</script>
